import time
import hashlib
from django.core import signing
from django.core.cache import cache
import bcrypt

"""
===================================
token，使用django加密解密、缓存
token = create_token(username)
1:加密;
2:解密;
3:生成token信息;
4:获取payload信息;
5:通过token获取用户名;
6:检测token;
7:密码加密;
8:密码验证;
9:file -> hash值;
===================================
"""

# django默认算法
HEADER = {'typ': 'JWP', 'alg': 'default'}
KEY = 'SHENG_NA_JI'
SALT = 'www.shennaji.com'
TIME_OUT = 2 * 60 * 60  # 2h


def encrypt(obj) -> str:
    """1:加密"""
    value = signing.dumps(obj, key=KEY, salt=SALT)
    value = signing.b64_encode(value.encode()).decode()
    return value


def decrypt(src) -> str:
    """2:解密"""
    src = signing.b64_decode(src.encode()).decode()
    raw = signing.loads(src, key=KEY, salt=SALT)
    return raw


def create_token(username) -> str:
    """3:生成token信息, header加密 + payload加密 + md5单向加密"""
    # 1. 加密头信息
    header = encrypt(HEADER)
    # 2. 构造Payload
    payload = {"username": username, "iat": time.time()}
    payload = encrypt(payload)
    # 3. 生成签名,使用md5（单向加密，无法解密）生成摘要signature，防止他人篡改token信息
    md5 = hashlib.md5()
    md5.update(("%s.%s" % (header, payload)).encode())
    signature = md5.hexdigest()
    token = "%s.%s.%s" % (header, payload, signature)
    # 存储到缓存中
    cache.set(username, token, TIME_OUT)
    return token


def get_payload(token):
    """
    4:获取payload信息
    """
    payload = str(token).split('.')[1]
    payload = decrypt(payload)
    return payload


def get_username(token):
    """
    5:通过token获取用户名"username"
    """
    payload = get_payload(token)
    return payload['username']


def check_token(token):
    """6:检测token"""
    username = get_username(token)
    last_token = cache.get(username)
    if last_token:
        return last_token == token
    return False


def set_bcrypt_password(password: str, encoding: str = 'UTF-8') -> str:
    """
    7:密码加密, 默认utf-8编码, 60字符
    :param password: 原密码
    :param encoding: 默认编码格式
    :return: 加密后的key
    """
    key = bcrypt.hashpw(password.encode(encoding=encoding), bcrypt.gensalt())
    return key.decode(encoding=encoding)


def validate_bcrypt_password(password: str, key: str, encoding: str = 'UTF-8') -> bool:
    """
    8:密码验证
    :param password: 原密码
    :param key: 加密后的字符串
    :param encoding: 默认编码解码格式
    """
    hash = bcrypt.hashpw(password.encode(encoding=encoding),
                         key.encode(encoding=encoding))
    if hash == key.encode(encoding=encoding):
        return True
    else:
        return False


def get_hash(file):
    """9:传入文件对象采用sha1获取文件hash值"""
    sha1obj = hashlib.sha1()
    sha1obj.update(file.read())
    hash = sha1obj.hexdigest()
    return hash